/*
 * uart.c
 *
 * Created: 2013-11-5 7:32:42
 *  Author: alivehex
 */
#include "uart.h"
#include "gpio.h"
#include "cbuf.h"
#include "hardware.h"

#include <stdarg.h>
#include <stdio.h>

static cbuf_t uartRxBuffer;
static char uartBuffer[32];

int uart1_open(unsigned long baudrate) {
	CBufInit(&uartRxBuffer, uartBuffer, sizeof(uartBuffer));
	
	PORTD |= (BOARD_DBG_TXD | BOARD_DBG_RXD);
	DDRD |= BOARD_DBG_TXD; // output
	DDRD &= ~BOARD_DBG_RXD; // input
	
	// baudrate and frame length etc.
	UBRRL= (F_CPU / baudrate / 8 - 1) % 256;
	UBRRH &= ~(1 << URSEL);
	UBRRH = ((F_CPU / baudrate / 8 - 1) / 256) & 0x0f;
	
	// double the rate
	UCSRA = (1 << 1);
	
	// 8bits and 1stop
	UCSRC = (1 << URSEL) | (3 << 1);
	
	// enable TX, RX and RXC interrupt
	UCSRB = (1 << 7) | (1 << 4) | (1 << 3);
	return 0;
}


int uart1_close(void) {
	PORTD &= ~(BOARD_DBG_TXD | BOARD_DBG_RXD);
	
	// disable tx and rx
	UCSRB &= ~(1 << 3) | (1 << 4 );
	return 0;
}

int uart1_putc(char c) {
	while ( ( UCSRA & (1 << 5)) == 0);
	UDR = c;
	return c;
}

int uart1_getc(int timeout) {
	if(timeout > 0) {
		while ( !(UCSRA & (1 << 7)) && (-- timeout));
		if(timeout == 0) {
			return -1;
		} else {
			return UDR;
		}
	} else {
		while ( !(UCSRA & (1 << 7)) );
		return UDR;
	}
	return 0;
}

int uart1_puts(char *c) {
	while (*c != 0) {
		uart1_putc(*c ++);
	}
	return 0;
}

void uart1_wait() {
	while ( !( UCSRA & (1 << 5)) );
}

ISR(USART_RXC_vect) {
	char data = UDR;
	
	CBufWrite(&uartRxBuffer, &data, 1);
	
	// echo back the data for debug
	// uart1_putc(data);
}

int uartRead(char *buffer, int len) {
	return CBufRead(&uartRxBuffer, buffer, len);
}

int kprintf(const char *str, ...) {
	char string[128];
	va_list ap;

	va_start(ap,str);
	vsprintf(string,str,ap);
	uart1_puts(string);
	va_end(ap);
	return 0;
}

//int kprintf(const char *str, ...) {
//	while(0);
//}	

